macOS Terminal Guide

Git on Mac
Complete Tutorial

From zero to version control master — every command you need to manage code, collaborate, and ship confidently using Terminal on macOS.

macOS Sequoia Terminal.app Git 2.x GitHub / GitLab Beginner → Advanced
01

Installation

macOS includes a basic version of Git, but the best way to get the latest is via Homebrew — the most popular package manager for Mac. Open Terminal (⌘ + Space → "Terminal") and run the commands below.

💡
OPEN TERMINAL FIRST Press ⌘ Space, type "Terminal", then hit Return. All commands below are typed directly into the Terminal prompt.
Install Homebrew (package manager)
$ # Paste this entire line into Terminal
$ /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
Install Git via Homebrew
$ brew install git
==> Downloading https://ghcr.io/v2/homebrew/core/git/...
==> Installing git
🍺 /opt/homebrew/Cellar/git/2.x.x: 1,643 files
Verify Installation
$ git --version
git version 2.47.0
ALTERNATIVE: XCODE COMMAND LINE TOOLS If you don't want Homebrew, run xcode-select --install in Terminal to install Apple's bundled version of Git. It's slightly older but works perfectly.
02

First-Time Configuration

Before making any commits, tell Git who you are. These values are embedded in every commit you create. Run this once per machine.

Set Your Identity
$ git config --global user.name "Your Name"
$ git config --global user.email "you@example.com"
Set Default Branch Name & Editor
$ git config --global init.defaultBranch main
$ git config --global core.editor nano # or "code --wait" for VS Code
View All Config Settings
$ git config --list
user.name=Your Name
user.email=you@example.com
init.defaultbranch=main
core.editor=nano
03

The Git Workflow

Git tracks changes through four areas. Understanding how files move between them is the key to mastering Git.

📝
Working
Directory
git add
📦
Staging
Area
git commit
🏠
Local
Repository
git push
☁️
Remote
Repository
Working Directory
📝 Your files on disk
Where you edit, create, and delete files normally. Git is watching but hasn't saved anything yet.
Staging Area (Index)
📦 git add <file>
A preparation zone. You choose exactly which changes to include in your next commit.
Local Repository
🏠 git commit -m "msg"
The permanent record on your Mac. Every commit is a snapshot saved in the .git folder.
Remote Repository
☁️ git push origin main
GitHub, GitLab, or Bitbucket. Shared cloud storage for collaboration and backup.
04

Init & Clone

Every Git project starts one of two ways: you initialize a new repository from scratch, or you clone an existing one from a remote server.

Create a New Repository from Scratch
$ mkdir my-project && cd my-project
$ git init
Initialized empty Git repository in /Users/you/my-project/.git/
Clone an Existing Repository
$ git clone https://github.com/user/repo.git
$ cd repo
Cloning into 'repo'...
remote: Counting objects: 245, done.
Receiving objects: 100% (245/245), 1.23 MiB | 4.5 MiB/s, done.
Clone into a Specific Folder Name
$ git clone https://github.com/user/repo.git my-folder
05

Staging & Commits

The daily Git loop: check status → stage changes → commit. Every commit is a permanent, labelled snapshot you can always return to.

Check the Status of Your Files
$ git status
On branch main
Changes not staged for commit:
    modified: index.html
Untracked files:
    styles.css
Stage Files
$ git add index.html # stage one file
$ git add styles.css app.js # stage multiple files
$ git add . # stage ALL changes in current dir
$ git add -p # interactive: stage chunks of changes
Create a Commit
$ git commit -m "Add navigation menu and footer"
$ git commit -am "Fix: correct typo in README" # add + commit tracked files
[main 3f2a1b7] Add navigation menu and footer
 2 files changed, 47 insertions(+), 3 deletions(-)
✍️
GOOD COMMIT MESSAGES Use the imperative mood: "Add login form" not "Added login form". Keep the first line under 72 characters. Great messages make git log a joy to read.
See Unstaged Differences
$ git diff # unstaged changes vs last commit
$ git diff --staged # staged changes vs last commit
$ git diff main..dev # compare two branches
06

Branches

Branches let you work on features or fixes in isolation without touching the main codebase. Think of them as parallel universes — you can switch between them instantly.

● ─── ● ─── ●──────────────────────● ← main
               ↘
                  ─── ─── ← feature/login
                 git checkout -b feature/login
Creating and Switching Branches
$ git branch # list all local branches
$ git branch feature/login # create a branch
$ git switch feature/login # switch to it (modern syntax)
$ git switch -c feature/signup # create AND switch in one step
$ git checkout -b feature/signup # older equivalent
Managing Branches
$ git branch -a # list ALL branches (local + remote)
$ git branch -d feature/login # delete (safe — won't delete unmerged)
$ git branch -D feature/login # force-delete unmerged branch
$ git branch -m old-name new-name # rename a branch
07

Merging & Rebasing

Once your feature is done, you need to bring it back into main. Merge preserves the branch history. Rebase rewrites it into a clean linear sequence. Both are valid — teams usually pick one convention.

Merge a Branch
$ git switch main # go to the target branch
$ git merge feature/login # merge feature into main
$ git merge --no-ff feature/login # always create a merge commit
Merge made by the 'recursive' strategy.
 login.html | 52 ++++++++++++
 1 file changed, 52 insertions(+)
⚠️
MERGE CONFLICTS When two branches edit the same lines, Git pauses and marks the conflict in the file. Open the file, find the <<<<<<< markers, pick the correct code, then run git add <file> and git commit to finish.
Rebase — Rewrite History Cleanly
$ git switch feature/login # be on the feature branch
$ git rebase main # replay commits on top of main
$ git rebase --abort # cancel a rebase in progress
$ git rebase --continue # after resolving conflicts
08

Remotes & GitHub

A "remote" is just a bookmark pointing to another copy of the repo — usually on GitHub. The standard remote is named origin.

Connect to a Remote
$ git remote add origin https://github.com/user/repo.git
$ git remote -v # verify remotes
origin  https://github.com/user/repo.git (fetch)
origin  https://github.com/user/repo.git (push)
Push, Pull, and Fetch
$ git push origin main # upload commits to GitHub
$ git push -u origin main # push and set upstream (first time)
$ git pull origin main # fetch + merge from GitHub
$ git fetch origin # download but don't merge
$ git push origin --delete feature/old # delete remote branch

Complete Workflow: Local project → GitHub

1

Create a repo on GitHub.com

Go to github.com → New → name it → don't initialize (no README). Copy the HTTPS URL.

2

Init, add files, and commit locally

git initgit add .git commit -m "Initial commit"

3

Connect and push

git remote add origin <URL>git push -u origin main

4

Work normally — push daily

Edit → git add .git commit -m "..."git push

09

Stash & Clean

Stash lets you temporarily shelve half-finished work so you can switch context, then come back and pop it out again.

Stash Commands
$ git stash # save dirty state
$ git stash push -m "WIP login" # stash with a name
$ git stash list # see all stashes
$ git stash pop # restore latest + delete stash
$ git stash apply stash@{1} # restore specific stash, keep it
$ git stash drop stash@{0} # delete a specific stash
$ git stash clear # delete ALL stashes
Clean Untracked Files
$ git clean -n # dry run: see what WOULD be deleted
$ git clean -fd # force-delete untracked files + dirs
10

Undoing Changes

Git gives you a safety net. No matter what you've done, there's almost always a way back. Here are the main escape hatches, from safest to most drastic.

Fix the Last Commit
$ git commit --amend -m "Better message" # change message
$ git commit --amend --no-edit # add staged file, keep message
Unstage & Discard Changes
$ git restore --staged index.html # unstage (keep changes in file)
$ git restore index.html # discard working dir changes ⚠️
$ git restore . # discard ALL working dir changes ⚠️
Reset Commits
$ git reset HEAD~1 # undo last commit, keep changes staged
$ git reset --soft HEAD~1 # undo last commit, keep changes staged
$ git reset --hard HEAD~1 # undo AND discard changes ⚠️ irreversible
$ git revert abc1234 # safe undo: creates a new reverting commit
🔥
NEVER USE --HARD ON PUSHED COMMITS git reset --hard on commits already pushed to GitHub will break history for your teammates. Use git revert instead — it's always safe.
11

Tags

Tags mark specific points in history — typically release versions like v1.0.0. Unlike branches, tags don't move.

Create and Push Tags
$ git tag # list all tags
$ git tag v1.0.0 # lightweight tag
$ git tag -a v1.0.0 -m "Version 1.0.0" # annotated tag (recommended)
$ git push origin v1.0.0 # push one tag
$ git push origin --tags # push all tags
$ git tag -d v1.0.0 # delete tag locally
12

Log & History

git log is your time machine — browse every commit, who made it, and what changed.

Viewing History
$ git log # full history
$ git log --oneline # compact one-line per commit
$ git log --oneline --graph --all # visual branch graph ✨
$ git log -5 # last 5 commits
$ git log -p index.html # history with diffs for one file
$ git log --author="Jane" # commits by a specific author
$ git log --since="2 weeks ago" # commits from last 2 weeks
$ git blame index.html # see who wrote each line
$ git show abc1234 # details of a specific commit
🎨
PRETTY LOG ALIAS Add this to ~/.zshrc or ~/.bash_profile for a beautiful log: alias gl='git log --oneline --graph --decorate --all'
13

Quick Reference

All the essential commands in one place.

Command What it does
git initCreate a new repository in the current folder
git clone <url>Download a remote repository to your Mac
git statusSee staged, unstaged, and untracked files
git add .Stage all changes in the current directory
git commit -m "msg"Save staged changes as a new commit
git push origin mainUpload commits to GitHub
git pullFetch + merge changes from remote
git fetchDownload changes without merging
git diffShow unstaged file differences
git log --onelineShow compact commit history
git switch -c branchCreate and switch to a new branch
git merge branchMerge a branch into the current branch
git rebase mainRewrite commits on top of main
git stashTemporarily save work-in-progress
git stash popRestore the last stash
git restore <file>Discard changes in working directory
git reset --soft HEAD~1Undo last commit, keep changes staged
git revert <hash>Safe undo: new commit that reverses changes
git tag -a v1.0 -m "…"Create an annotated release tag
git blame <file>See who wrote each line in a file

The .gitignore file — create this in your project root to exclude files from tracking (node_modules, build output, secrets, etc.)

Sample .gitignore for a Mac web project
# ~/.gitignore or project/.gitignore
node_modules/ # npm packages
dist/ # build output
.env # secret keys — never commit!
.DS_Store # macOS folder metadata
*.log # any log files